/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.testis.utils;

import java.io.IOException;
import java.net.BindException;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Enumeration;

/**
 * A class to define simple networking methods
 * @author nurhat
 */
public class Networking {

    /**
     * Returns an available port
     * @param startCheckFrom Starting check point  
     * @return first available port from checking starting point
     */
    public static int getAvailablePort(int startCheckFrom) {
        try {
            ServerSocket sock = new ServerSocket(startCheckFrom);
            sock.close();
            return startCheckFrom;
        } catch (BindException b) {
            startCheckFrom++;

        } catch (IOException e) {
        }
        return getAvailablePort(startCheckFrom);
    }

    /**
     * Checks availability of a port
     * @param port  check port  
     * @return if available port returns true else returns false
     */
    public static boolean isAvailablePort(int port) {
        ServerSocket sock = null;
        boolean result = false;
        try {
            sock = new ServerSocket(port);
            result = true;
        } catch (BindException b) {
        } catch (IOException e) {
        } finally {
            if (sock != null) {
                try {
                    sock.close();
                } catch (IOException ex) {
                }
            }
        }
        return result;
    }

    public static boolean isUdpAvailable(int port) {
        DatagramSocket ds = null;
        boolean result=false;
        try {
            ds = new DatagramSocket(port);
            ds.setReuseAddress(true);
            result= true;
        } catch (IOException e) {
        } finally {
            if (ds != null) {
                ds.close();
            }
        }

        return result;
    }

    /**
     * finds all ips on the local computer
     * @return  an  arraylist of string that contains ips
     */
    public static ArrayList<String> getIps() {
        ArrayList<String> ips = new ArrayList<String>();
        try {
            Enumeration e = NetworkInterface.getNetworkInterfaces();

            while (e.hasMoreElements()) {
                NetworkInterface netface = (NetworkInterface) e.nextElement();

                // System.out.println("Net interface: " + netface.getName());

                Enumeration e2 = netface.getInetAddresses();

                while (e2.hasMoreElements()) {
                    InetAddress ip = (InetAddress) e2.nextElement();
                    ips.add(ip.toString());
                //  System.out.println("IP address: " + ip.toString());
                }
            }
        } catch (Exception e) {
            System.out.println("error: " + e);
        }
        return ips;
    }

    /**
     * finds all mac addresses on the local computer
     * @return  an  arraylist of string that contains ips
     */
    public static ArrayList<String> getMacAddresses() {
        ArrayList<String> macs = new ArrayList<String>();
        try {
            Enumeration e = NetworkInterface.getNetworkInterfaces();

            while (e.hasMoreElements()) {
                NetworkInterface netface = (NetworkInterface) e.nextElement();

                byte[] mac = netface.getHardwareAddress();
                StringBuilder sb;
                if (mac != null) {
                    sb = new StringBuilder();
                    for (int i = 0; i < mac.length; i++) {
                        sb.append(String.format("%02X%s",
                                mac[i],
                                (i < mac.length - 1) ? "-" : ""));
                    }
                    macs.add(sb.toString());
                }
            }
        } catch (Exception e) {
            System.out.println("error: " + e);
        }
        return macs;
    }

    /**
     * Checks given mac address whether related to local computer or not
     * @param lookUpIp
     * @return return true if mac address is found on local computer, otherwise returns false
     */
    public static boolean isMacExists(String lookUpMac) {
        if (lookUpMac == null) {
            return false;
        }
        ArrayList<String> macList = Networking.getMacAddresses();

        for (int i = 0; i < macList.size(); i++) {

            if (lookUpMac.equals(macList.get(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks given ip whether related to local computer or not
     * @param lookUpIp
     * @return return true if ip is found on local computer, otherwise returns false
     */
    public static boolean isIpExists(String lookUpIp) {
        if (lookUpIp == null) {
            return false;
        }
        ArrayList<String> ipList = Networking.getIps();
        String[] tmp;
        for (int i = 0; i < ipList.size(); i++) {
            //ipList.get(i) returns "hostname / literal IP" 
            tmp = ipList.get(i).split("/");
            if (lookUpIp.equals(tmp[1])) {
                return true;
            }
        }
        return false;
    }
}
